// Keywords: logistic growth, logistic population model, carrying capacity, density dependence

initialize() {
	defineConstant("K", 50000);
	defineConstant("R", 1.1);
	defineConstant("M", K / (R - 1));
	
	initializeSLiMModelType("nonWF");
	initializeMutationType("m1", 0.5, "f", 0.0);
	m1.convertToSubstitution = T;
	initializeGenomicElementType("g1", m1, 1.0);
	initializeGenomicElement(g1, 0, 99999);
	initializeMutationRate(1e-7);
	initializeRecombinationRate(1e-8);
}
1 early() {
	sim.addSubpop("p1", 50);   // the "simple model"
	sim.addSubpop("p2", 50);   // Beverton-Holt influencing fecundity
	sim.addSubpop("p3", 50);   // Beverton-Holt influencing survival
	
	log = community.createLogFile("sim_log.txt", logInterval=1);
	log.addCycle();
	log.addSubpopulationSize(p1);
	log.addSubpopulationSize(p2);
	log.addSubpopulationSize(p3);
}
reproduction(p1) {
	// p1 simply reproduces with a mean litter size of R, like p3
	litterSize = rpois(1, R);
	for (i in seqLen(litterSize))
		subpop.addCrossed(individual, subpop.sampleIndividuals(1));
}
reproduction(p2) {
	// p2 reproduces up to the Beverton-Holt equation's target
	n_t = subpop.individualCount;
	n_t_plus_1 = (R * n_t) / (1 + n_t / M);
	mean_litter_size = n_t_plus_1 / n_t;
	litterSize = rpois(1, mean_litter_size);
	
	for (i in seqLen(litterSize))
		subpop.addCrossed(individual, subpop.sampleIndividuals(1));
}
reproduction(p3) {
	// p3 simply reproduces with a mean litter size of R, like p1
	litterSize = rpois(1, R);
	for (i in seqLen(litterSize))
		subpop.addCrossed(individual, subpop.sampleIndividuals(1));
}
early() {
	// p1 uses the "simple model" with non-overlapping generations
	inds = p1.individuals;
	inds[inds.age > 0].fitnessScaling = 0.0;
	n_t_plus_pt5 = sum(inds.age == 0);
	p1.fitnessScaling = K / n_t_plus_pt5;
	
	// p2 has selection only to achieve non-overlapping generations
	inds = p2.individuals;
	inds[inds.age > 0].fitnessScaling = 0.0;
	
	// p3 uses the Beverton-Holt equation for survival
	inds = p3.individuals;
	inds[inds.age > 0].fitnessScaling = 0.0;
	n_t_plus_pt5 = sum(inds.age == 0);
	p3.fitnessScaling = 1 / (1 + (n_t_plus_pt5 / R) / M);
}
200 late() {
	// log out the final row before plotting
	log = community.logFiles;
	log.logRow();
	log.setLogInterval(NULL);
	
	// make a final plot
	if (exists("slimgui"))
	{
		cycle_data = slimgui.logFileData(log, "cycle");
		p1_data = slimgui.logFileData(log, "p1_num_individuals");
		p2_data = slimgui.logFileData(log, "p2_num_individuals");
		p3_data = slimgui.logFileData(log, "p3_num_individuals");
		
		plot = slimgui.createPlot("Population Growth",
			xlab="Generation", ylab="Population size",
			width=500, height=250);
		
		plot.abline(h=50000, color="#999999", lwd=1.0);
		
		plot.lines(cycle_data, p1_data, "cornflowerblue", lwd=2);
		plot.lines(cycle_data, p2_data, "red", lwd=2);
		plot.lines(cycle_data, p3_data, "chartreuse3", lwd=2);
		
		plot.addLegend("topLeft", inset=0, labelSize=13);
		plot.legendLineEntry("p1", "cornflowerblue", lwd=2);
		plot.legendLineEntry("p2", "red", lwd=2);
		plot.legendLineEntry("p3", "chartreuse3", lwd=2);
		
		plot.write("Population Growth.pdf");
	}
}
